#pragma once

#include <slice.h>
#include <status.h>

#include <functional>

namespace minidb
{
class Iterator
{
public:
    Iterator();

    Iterator(const Iterator &) = delete;
    Iterator &operator=(const Iterator &) = delete;

    virtual ~Iterator();

    virtual bool Vaild() const = 0;

    virtual void SeekToFirst() = 0;

    virtual void SeekToLast() = 0;

    virtual void Seek(const Slice &target) = 0;

    virtual void Next() = 0;

    virtual void Prev() = 0;

    virtual Slice key() const = 0;

    virtual Slice value() const = 0;

    virtual Status status() const = 0;

    using CleanupFunction = std::function<void(void *, void *)>;

    void RegisterCleanup(CleanupFunction function, void *arg1, void *arg2);

private:
    struct CleanupNode
    {
        bool IsEmpty() const
        {
            return func_ == nullptr;
        }

        void Run()
        {
            assert(func_ != nullptr);
            func_(arg1_, arg2_);
        }

        CleanupFunction func_;
        void *arg1_;
        void *arg2_;
        CleanupNode *next_;
    };

    CleanupNode cleanup_head_;
};
}; // namespace minidb